
/******************************************************************************
 * MODULE     : math_tree.hpp
 * DESCRIPTION: trees as mathematical expressions
 * COPYRIGHT  : (C) 2006  Joris van der Hoeven
 *******************************************************************************
 * This software falls under the GNU general public license version 3 or later.
 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
 ******************************************************************************/

#ifndef MATH_TREE_H
#define MATH_TREE_H
#include "tree_helper.hpp"

tree neg (tree t1);
tree add (tree t1, tree t2);
tree sub (tree t1, tree t2);
tree mul (tree t1, tree t2);
tree div (tree t1, tree t2);

tree sqrt (tree t);
tree exp (tree t);
tree log (tree t);
tree pow (tree t1, tree t2);
tree sin (tree t);
tree cos (tree t);
tree tan (tree t);

string as_math_string (tree t);

template <typename T>
void
parse (tree t, T& result) {
  (void) t;
  (void) result;
  TM_FAILED ("unsupported type");
}

inline void
parse (tree t, double& result) {
  ASSERT (is_double (t), "not a double");
  result= as_double (t);
}

template <typename T>
T
parse_as (tree t) {
  switch (L (t)) {
  case moebius::PLUS:
    return parse_as<T> (t[0]) + parse_as<T> (t[1]);
  case moebius::MINUS:
    if (N (t) == 1) return -parse_as<T> (t[0]);
    else return parse_as<T> (t[0]) - parse_as<T> (t[1]);
  case moebius::TIMES:
    return parse_as<T> (t[0]) * parse_as<T> (t[1]);
  case moebius::OVER:
    return parse_as<T> (t[0]) / parse_as<T> (t[1]);
  case moebius::MATH_SQRT:
    return sqrt (parse_as<T> (t[0]));
  case moebius::EXP:
    return exp (parse_as<T> (t[0]));
  case moebius::LOG:
    return log (parse_as<T> (t[0]));
  case moebius::POW:
    return pow (parse_as<T> (t[0]), parse_as<T> (t[1]));
  case moebius::COS:
    return cos (parse_as<T> (t[0]));
  case moebius::SIN:
    return sin (parse_as<T> (t[0]));
  case moebius::TAN:
    return tan (parse_as<T> (t[0]));
  default: {
    T result;
    parse (t, result);
    return result;
  }
  }
}

#endif // defined MATH_TREE_H
